package com.focus.pay.wx.model.order.v2;

import cn.hutool.core.annotation.PropIgnore;
import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.core.bean.copier.CopyOptions;
import com.focus.pay.core.domain.PayModelDomain;
import com.focus.pay.core.exception.ExceptionEnum;
import com.focus.pay.core.exception.PayException;
import com.focus.pay.wx.config.WxPayConfig;
import com.focus.pay.wx.constant.WxPayConstant;
import com.focus.pay.core.enums.Version;
import com.focus.pay.core.utils.StringUtils;
import lombok.Data;
import com.focus.pay.wx.utils.WxPayUtils;

import java.util.*;

/**
 * 微信支付公共参数
 */
@Data
public class WxPayCommon extends PayModelDomain {

    /**
     * 微信分配的公众账号ID
     */
    private String appid;

    /**
     * 子商户公众账号ID
     */
    private String sub_appid;

    /**
     * 微信支付分配的商户号
     */
    private String mch_id;

    /**
     * 子商户号
     */
    private String sub_mch_id;

    /**
     * 随机字符串
     */
    private String nonce_str;

    /**
     * 签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
     */
    private String sign_type;

    /**
     * 签名
     */
    private String sign;

    /**
     * 秘钥
     */
    @PropIgnore
    private String key;




    /**
     * 构建微信支付参数
     * @param <T>  支付类
     * @param wxPayConfig 微信配置
     * @return 请求属性
     */
    public <T extends WxPayCommon> T buildParam(T t, WxPayConfig wxPayConfig) {
        t.setAppid(wxPayConfig.getAppId());
        t.setMch_id(wxPayConfig.getMchId());

        t.setNonce_str(WxPayUtils.buildNonceStr());
        t.setSign_type(Objects.isNull(wxPayConfig.getSignType())?
                wxPayConfig.getSignType().replace("-","").toUpperCase() : WxPayConstant.WxPayEncryptionType.MD5.toString());
        t.setKey(wxPayConfig.getKey());
        //兼容服务商模式
        if(StringUtils.isNotEmpty(wxPayConfig.getSubAppid()))
            t.setSub_appid(wxPayConfig.getSubAppid());
        if (StringUtils.isNotEmpty(wxPayConfig.getSubMchId()))
            t.setSub_mch_id(wxPayConfig.getSubMchId());
        return t;
    }

    /**
     * 构建请求参数
     * @param <T>  支付类
     * @return  请求参数
     */
    public <T extends WxPayCommon> String buildRequestParam(T t) throws PayException {
        t.setSign(buildSign(t));
        return WxPayUtils.beanToXmlStr(t);
    }

    /**
     * 构建签名字符串
     * @param <T> 支付类
     * @return
     */
    public <T extends WxPayCommon> String buildSign(T t) throws PayException {
        HashMap<String,String> paramMap = BeanCopier.create(t,new HashMap<String,String>(), CopyOptions.create().ignoreNullValue()).copy();
        String encryptionParamsStr = WxPayUtils.buildSignStr(paramMap,t.getKey(), Version.VERSION_2);
        //签名
        if(WxPayConstant.WxPayEncryptionType.MD5.toString().equals(t.getSign_type().toUpperCase())){
           return  WxPayUtils.MD5Encryption(encryptionParamsStr);
        }else if(WxPayConstant.WxPayEncryptionType.HMACSHA256.equals(t.getSign_type().replace("-","").toUpperCase())){
           return  WxPayUtils.HMACSHA256Encryption(encryptionParamsStr,t.getKey());
        }else{
            throw new PayException(ExceptionEnum.SIGN_ERROR);
        }
    }
}
